﻿// JavaScript Document

// should have a resource manager. but defer to do that.

var TOOL_STATE_DRAG = 0;
var TOOL_STATE_FANDI = 1;
var TOOL_STATE_HARVEST = 2;
var TOOL_STATE_HARVEST_ALL = 3;
var TOOL_STATE_ITEM = 4;
var TOOL_STATE_KILL_WEEDS = 5;
var TOOL_STATE_KILL_WORMS = 6;
var TOOL_STATE_WATER = 7;
var TOOL_STATE_PLACE_WORMS = 8;

// this is displayObject
function StatusBar(name)
{
    if (this instanceof StatusBar)
    {
        this.name = name;
        this.exp = 0;
    }
    else
    {
        return new StatusBar(name);
    }
}

StatusBar.prototype.draw = function(ctx, x, y)
{
    var text = "名字:" + this.name + "  经验:" + this.exp;
    var metrix = ctx.measureText(text);
    var fontW = metrix.width + 8;
    var fontH = 10 + 6;
    ctx.fillStyle = "rgba(255, 255, 255, 0.2)";
    ctx.strokeStyle = "rgba(0, 0, 0, 1)";
    ctx.textBaseline = "top";
    ctx.fillRect(x, y, fontW, fontH);
    ctx.strokeText(text, x + 1, y + 2);
}

StatusBar.prototype.updateStatus = function(farm)
{
    this.exp = farm.getExp();
}

function FarmState(ctx)
{
    if (this instanceof FarmState)
    {
        this.ctx = ctx;
        this.focusNode = null;
        this.toolState = TOOL_STATE_DRAG;
    }
    else
    {
        return new FarmState(ctx);
    }
}

FarmState.prototype.onEnter = function()
{
    log.info("enter farm state");
    // first register needed animation.
    // maybe need a tool to handle animation. but now have no it.
    this.registerAnimation();
    
    this.cursorPos = new Point(0, 0);
    
    // game scene. rendered in canvas.
    this.gameRoot = new SceneNode(null);
    this.uiRoot = new SceneNode(null);
    
    this.renderer = new Renderer();
    this.camera = new Camera(this.gameRoot, new Point(CANVAS_WIDTH, CANVAS_HEIGHT));
    this.camera.setPosition(new Point(0, 50));
    log.info("farm state: create camera ok");
    this.background = new Background(this.gameRoot);
    this.farmTipWindow = new FarmTipWindow();
    this.farmView = new FarmView(this.gameRoot, this.farmTipWindow, this, Models.getModels().getFarm());
    this.farmView.setPosition(new Point(40, 275));
    log.info("farm state: create farm view ok");

    // ui. rendered in dom.
    // bottom action bar. the bar will be extended future. and will be changed when environment changes.
    this.bottomToolBar = new UI.ToolBar();
    UI.getManager().appendWidget(this.bottomToolBar);
    var bottomToolItemWidth = 56;
    var bottomToolItemHeight = 56;
    new ImageObject(g_imgMgr.getImage(IMAGE_FARM_BLOCK_COMMON), new Point(0, 0));
    this.bottomToolBar.addImgItem(UI.makeImageRenderFormat(ICON_DRAG, new Point(5, 5)),
				  new Point(bottomToolItemWidth, bottomToolItemHeight), 
				  bind(this.onDrag, this));
    this.bottomToolBar.addImgItem(UI.makeImageRenderFormat(ICON_FANDI, new Point(5, 5)),
				  new Point(bottomToolItemWidth, bottomToolItemHeight), 
				  bind(this.onFandi, this));
    this.bottomToolBar.addImgItem(UI.makeImageRenderFormat(ICON_HARVEST, new Point(0, 6)),
				  new Point(bottomToolItemWidth, bottomToolItemHeight), 
				  bind(this.onHarvest, this));
    this.bottomToolBar.addImgItem(UI.makeImageRenderFormat(ICON_HARVEST_ALL, new Point(-9, -2)),
				  new Point(bottomToolItemWidth, bottomToolItemHeight), 
				  bind(this.onHarvestAll, this));
    this.bottomToolBar.addImgItem(UI.makeImageRenderFormat(ICON_ITEMS, new Point(3, 2)),
				  new Point(bottomToolItemWidth, bottomToolItemHeight), 				
				  bind(this.onItems, this));
    this.bottomToolBar.addImgItem(UI.makeImageRenderFormat(ICON_KILL_WEEDS, new Point(3, 4)),
				  new Point(bottomToolItemWidth, bottomToolItemHeight), 		
				  bind(this.onKillWeeds, this));
    this.bottomToolBar.addImgItem(UI.makeImageRenderFormat(ICON_KILL_WORMS, new Point(1, 5)),
				  new Point(bottomToolItemWidth, bottomToolItemHeight), 		
				  bind(this.onKillWorms, this));
    this.bottomToolBar.addImgItem(UI.makeImageRenderFormat(ICON_WATER, new Point(-1, 5)),
				  new Point(bottomToolItemWidth, bottomToolItemHeight), 		
				  bind(this.onWater, this));
    this.bottomToolBar.setPosition(new Point(200, 480));
    log.info("farm state: create bottom tool bar ok");
    
    // top bar. contains warehouse and shop.
    this.topToolBar = new UI.ToolBar();
    UI.getManager().appendWidget(this.topToolBar);
    this.topToolBar.addImgItem(UI.makeImageRenderFormat(ICON_SHOP), new Point(48, 48), 
			       bind(this.onShop, this));
    this.topToolBar.addImgItem(UI.makeImageRenderFormat(ICON_WARE_HOUSE), new Point(48, 48), 
			       bind(this.onWarehouse, this));
    this.topToolBar.setPosition(new Point(700, 10));
    log.info("farm state: create top tool bar ok");
    
    // status bar. will be riched.
    this.statusBar = new StatusBar("李宁");
    new SceneNode(this.uiRoot, this.statusBar);
    Models.getModels().getFarm().registerListener(Models.Event.User.STATUS, bind(this.statusBar.updateStatus, this.statusBar));
    log.info("create status bar ok");

    // manage focus and drag. temporary, need rewrite.
    this.clickDownTarget = null;
    this.clickDownPos = new Point(0, 0);
    this.lastCursorPos = new Point(0, 0);
    this._isDragging = false;
    this.setToolState(TOOL_STATE_DRAG);
    log.info("farm state init success");
}

FarmState.prototype.allowDragging = function()
{
    return this.toolState == TOOL_STATE_DRAG;
}

FarmState.prototype.onExit = function()
{
    log.info("farm state exit");
    this.background = null;
    this.farmView = null;
    this.bottomToolBar = null;
    this.topToolBar = null;
    
    this.renderer = null;
    this.camera = null;
    this.gameRoot = null;
    this.uiRoot = null;
}

FarmState.prototype.registerAnimation = function()
{
    log.info("farm state register animation");
    g_aniMgr.unregisterAll();
    g_aniMgr.registerAnimationCloseByImageList("cursor_kill_worm", g_imgMgr, CURSOR_ANI_KILL_WORM, 3, 0.1);
    g_aniMgr.registerAnimationCloseByImageList("cursor_harvest", g_imgMgr, CURSOR_ANI_HARVEST, 2, 0.2);
    g_aniMgr.registerAnimationCloseByImageList("cursor_place_worm", g_imgMgr, CURSOR_PLACE_WORM, 2, 0.2);
    log.info("register animation ok");
}

FarmState.prototype.update = function(interval)
{
    // update scene.
    this.gameRoot.update(false);
    this.uiRoot.update(false);
    // update game logic.
    this.farmView.update(interval);
    this.background.update(interval);
    this.bottomToolBar.update(interval);
    this.topToolBar.update(interval);
    // update models.
    Models.getModels().update(interval);
}

FarmState.prototype.draw = function()
{
    // clear screen.
    this.ctx.fillStyle = 'rgba(255, 255, 255, 1)';
    this.ctx.fillRect(0, 0, CANVAS_WIDTH, CANVAS_HEIGHT);
    // if has viewport or camera like. set ctx.
    this.drawGame();
    this.drawUI();
}

FarmState.prototype.drawGame = function()
{
    var renderList = [];
    this.camera.filterScene(this.gameRoot, renderList);
    this.renderer.render(renderList, this.ctx, this.camera);
    this.farmTipWindow.draw(this.ctx, this.cursorPos.x, this.cursorPos.y);
    this.farmView.draw(this.ctx);
}

FarmState.prototype.drawUI = function()
{
    this.uiRoot.draw(this.ctx);
}

FarmState.prototype.hitTest = function(pt)
{
    var newpt = this.camera.translatePos(pt);
    return this.uiRoot.hitTest(pt) || this.gameRoot.hitTest(newpt);
}

FarmState.prototype.moveCamera = function(offset)
{
    var pos = Point.s_add(this.camera.getPosition(), offset);
    if (pos.x < 0) pos.x = 0;
    if (pos.y < 0) pos.y = 0;
    if (pos.x + CANVAS_WIDTH > WORLD_WIDTH) pos.x = WORLD_WIDTH - CANVAS_WIDTH;
    if (pos.y + CANVAS_HEIGHT > WORLD_HEIGHT) pos.y = WORLD_HEIGHT - CANVAS_HEIGHT;
    this.camera.setPosition(pos);
}

FarmState.prototype.startDragging = function(pt)
{
    this._isDragging = true;
    getApp().setImgCursor(g_imgMgr.getImage(CURSOR_DRAG));
    this.lastCursorPos.setValue(pt);
}

FarmState.prototype.moveDragging = function(pt)
{
    var offset = Point.s_sub(this.lastCursorPos, pt);
    this.moveCamera(offset);
    this.lastCursorPos.setValue(pt);
}

FarmState.prototype.endDragging = function()
{
    this._isDragging = false;
    // if multi state support dragging, here will setAni by switch. same as startDragging.
    getApp().setImgCursor(g_imgMgr.getImage(CURSOR_COMMON));
}

FarmState.prototype.clickFarmBlock = function(model_block)
{
    log.info("farm state::clickFarmBlock");
    assert(model_block, "clickFarmBlock: every block view must listener some block model!");
    
    switch(this.toolState)
    {
    case TOOL_STATE_DRAG:
	break;
    case TOOL_STATE_FANDI:
	model_block.fandi();
	break;
    case TOOL_STATE_HARVEST:
	getApp().startCursorAnimation();
	model_block.harvest();
	break;
    case TOOL_STATE_HARVEST_ALL:
	getApp().startCursorAnimation();
	model_block.getParentFarm().harvestAll();
	break;
    case TOOL_STATE_ITEM:
	// should have a put seeds state. but now use this state to sample.
	model_block.plant(StaticModels.getRandomFakeVegName());	// should give a parameter to indicate which type of seeds. but now fake no.
	break;
    case TOOL_STATE_KILL_WEEDS:
	// no this now.
	getApp().startCursorAnimation();
	model_block.killWeeds();
	break;
    case TOOL_STATE_KILL_WORMS:
	getApp().startCursorAnimation();
	model_block.killWorms();
	break;
    case TOOL_STATE_WATER:
	// no water images. use worms to placeholder.
	//		getApp().startCursorAnimation();
	model_block.water();
	break;
    case TOOL_STATE_PLACE_WORMS:
	getApp().startCursorAnimation();
	// should not place worm to self, but no only self. so this is for sample.
	model_block.placeWorms();
	break;
    default:
	break;
    }
}

FarmState.prototype.onMouseDown = function(pt)
{
    this.cursorPos.setValue(pt);
    var target = this.hitTest(pt);
    if (this.focusNode != target)
    {
        if (this.focusNode)
        {
            this.focusNode.onMouseLeave();
        }
        if (target)
        {
            target.onMouseOver();
        }
    }
    if (target)
    {
        target.onMouseDown();
	this.clickDownTarget = target;
	this.clickDownPos.setValue(pt);
    }
    this.focusNode = target;
    if (this.allowDragging())
    {
	this.startDragging(pt);
    }
}

FarmState.prototype.onMouseMove = function(pt)
{
    this.cursorPos.setValue(pt);
    if (this.allowDragging() && this._isDragging)
    {
	this.moveDragging(pt);
    }
    else
    {
	var target = this.hitTest(pt);
	if (this.focusNode != target)
	{
	    if (this.focusNode)
	    {
		this.focusNode.onMouseLeave();
	    }
	    if (target)
	    {
		target.onMouseOver();
	    }
	}
	this.focusNode = target;		
    }
}

FarmState.prototype.onMouseUp = function(pt)
{
    this.cursorPos.setValue(pt);
    if (this.allowDragging())
    {
	this.endDragging();
    }
    var target = this.hitTest(pt);
    if (this.focusNode != target)
    {
        if (this.focusNode)
        {
            this.focusNode.onMouseLeave();
        }
        if (target)
        {
            target.onMouseOver();
        }
    }
    if (target)
    {
	target.onMouseUp();
	if (this.clickDownTarget == target && this.clickDownPos.distance(pt) < 10)
	{
	    target.onMouseClick();
	}
    }
    this.focusNode = target;
}

FarmState.prototype.onMouseOut = function()
{
    var target = null;
    if (this.focusNode != target)
    {
        if (this.focusNode)
        {
            this.focusNode.onMouseLeave();
        }
        if (target)
        {
            target.onMouseOver();
        }
    }
    this.focusNode = target;
    if (this.allowDragging())
    {
	this.endDragging();
    }
}
//TODO.  move cursor action to some functions.
FarmState.prototype.setToolState = function(state)
{
    if (this.toolState == state) return;
    this.endDragging();
    switch(state)
    {
    case TOOL_STATE_DRAG:
	getApp().setImgCursor(g_imgMgr.getImage(CURSOR_COMMON));
	break;
    case TOOL_STATE_FANDI:
	getApp().setImgCursor(g_imgMgr.getImage(CURSOR_FANDI), new Point(-5, -100));
	break;
    case TOOL_STATE_HARVEST:
	var ani = g_aniMgr.getAnimation("cursor_harvest");
	ani.end();
	getApp().setImgCursor(ani, new Point(-5, -40));
	break;
    case TOOL_STATE_HARVEST_ALL:
	var ani = g_aniMgr.getAnimation("cursor_harvest");
	ani.end();
	getApp().setImgCursor(ani, new Point(-5, -40));
	break;
    case TOOL_STATE_ITEM:
	// should get items from selected images. but now have no. so use a placeholder.
	getApp().setImgCursor(g_imgMgr.getImage(CURSOR_SEEDS), new Point(-5, -5));
	break;
    case TOOL_STATE_KILL_WEEDS:
	// no this now.
	getApp().setImgCursor(g_imgMgr.getImage(CURSOR_COMMON));
	break;
    case TOOL_STATE_KILL_WORMS:
	var ani = g_aniMgr.getAnimation("cursor_kill_worm");
	ani.end();
	getApp().setImgCursor(ani, new Point(-5, -50));
	break;
    case TOOL_STATE_WATER:
	// no water images. use worms to placeholder.
	var ani = g_aniMgr.getAnimation("cursor_kill_worm");
	ani.end();
	getApp().setImgCursor(ani, new Point(-5, -50));
	break;
    case TOOL_STATE_PLACE_WORMS:
	var ani = g_aniMgr.getAnimation("cursor_place_worm");
	ani.end();
	getApp().setImgCursor(ani, new Point(-5, -35));
	break;
    default:
	break;
    }
    this.toolState = state;
    log.info("farm state: switch to farm state" + state);
}

FarmState.prototype.onDrag = function()
{
    this.setToolState(TOOL_STATE_DRAG);
}

FarmState.prototype.onFandi = function()
{
    log.debug("start fandi!");
    this.setToolState(TOOL_STATE_FANDI);
}

FarmState.prototype.onHarvest = function()
{
    log.debug("start harvest");
    this.setToolState(TOOL_STATE_HARVEST);
}

FarmState.prototype.onHarvestAll = function()
{
    log.debug("start harvest all");
    this.setToolState(TOOL_STATE_HARVEST_ALL);
}

FarmState.prototype.onItems = function()
{
    log.debug("now dont select items. only start put harvest!");
    this.setToolState(TOOL_STATE_ITEM);
}

FarmState.prototype.onKillWeeds = function()
{
    log.debug("now this is placeholder for place worms. ");
    this.setToolState(TOOL_STATE_PLACE_WORMS);
}

FarmState.prototype.onKillWorms = function()
{
    log.debug("kill worms!");
    this.setToolState(TOOL_STATE_KILL_WORMS);
}

FarmState.prototype.onWater = function()
{
    log.debug("no water animation, but can has actions!");
    this.setToolState(TOOL_STATE_WATER);
}

FarmState.prototype.onShop = function()
{
    log.debug("shop item!");
    var shop = new Shop();
    shop.doModal();
}

FarmState.prototype.onWarehouse = function()
{
    log.debug("warehouse item!");
    var warehouse = new Warehouse();
    warehouse.doModal();
}
